package com.futureCloudMOM.controller.core.utils;

import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.futureCloudMOM.common.core.domain.AjaxResult;
import com.futureCloudMOM.common.core.domain.entity.SysDictData;
import com.futureCloudMOM.common.core.page.TableDataInfo;
import com.futureCloudMOM.framework.dict.Dict;
import com.futureCloudMOM.system.service.ISysDictTypeService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@Aspect
@Component
@Slf4j
public class DictAspect {
    /**
     * 字典后缀
     */
    private static final String DICT_TEXT_SUFFIX = "Text";

    @Autowired
    private ISysDictTypeService dictTypeService;

    /**
     * 切点，切入 controller 包下面的所有方法
     */
//    @Pointcut("execution( * com.futureCloudMOM.*.controller.huandian.*.*(..)) || execution( * com.futureCloudMOM.*.controller.*.*(..)) ")
    @Pointcut("execution( * com.futureCloudMOM.controller.core.web.*.*.*(..)) || execution(* com.futureCloudMOM.controller.core.*.*.*(..)))")
    public void dict() {

    }

    @Around("dict()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        long time1 = System.currentTimeMillis();
        Object result = pjp.proceed();
        long time2 = System.currentTimeMillis();
        log.debug("获取JSON数据 耗时：" + (time2 - time1) + "ms");
        long start = System.currentTimeMillis();
        this.parseDictText(result);
        long end = System.currentTimeMillis();
        log.debug("解析注入JSON数据  耗时" + (end - start) + "ms");
        return result;
    }


    private void parseDictText(Object result) {
        List<JSONObject> items = new ArrayList<>();
        if (result instanceof AjaxResult) {
            AjaxResult rr = (AjaxResult) result;
            Object object = rr.get(AjaxResult.DATA_TAG);
            if (object instanceof String || object == null) {
                //字符串直接返回
                rr.put(AjaxResult.DATA_TAG, object);
            } else {
                rr.put(AjaxResult.DATA_TAG, getDataModel(object));
            }
        } else if (result instanceof TableDataInfo) {
            TableDataInfo rr = (TableDataInfo) result;
            List<?> list = (List<?>) rr.getRows();
            getData(items, list);
            rr.setRows(items);
        }
    }


    private void getData(List<JSONObject> items, List<?> listData) {
        List<?> list = listData;
        for (Object record : list) {
            ObjectMapper mapper = new ObjectMapper();
            String json = "{}";
            try {
                json = mapper.writeValueAsString(record);
            } catch (JsonProcessingException e) {
                log.error("Json解析失败：" + e);
            }
            JSONObject item = JSONObject.parseObject(json);
            ObjConvertUtils o = new ObjConvertUtils();
            for (Field field : o.getAllFields(record)) {
                if (field.getAnnotation(Dict.class) != null) {
                    // 拿到注解的dictCode属性的值
                    String dictType = field.getAnnotation(Dict.class).dictCode();
                    // 拿到注解的dictText属性的值
                    String text = field.getAnnotation(Dict.class).dictText();
                    // 拿到注解的dictTable属性的值
                    String table = field.getAnnotation(Dict.class).dictTable();
                    //获取当前带翻译的值
                    String key = String.valueOf(item.get(field.getName()));

                    //如果table有值 说明是做id翻译
                    if (!StringUtils.isBlank(table)) {
                        try {
                            if (ObjectUtils.isNotEmpty(key) & !"null".equals(key)) {
                                item.put(field.getName() + DICT_TEXT_SUFFIX, dictTypeService.dictTable(table, text, dictType, key));
                            } else {
                                item.put(field.getName() + DICT_TEXT_SUFFIX, null);
                            }
                        } catch (Exception e) {
                            throw new RuntimeException(field.getName() + "字段翻译异常");
                        }
                    } else {
                        //翻译字典值对应的text值
                        String textValue = translateDictValue(dictType, key);
                        // 走默认策略
                        item.put(field.getName() + DICT_TEXT_SUFFIX, textValue);
                    }
                }
                // date类型默认转换string格式化日期
                if ("java.util.Date".equals(field.getType().getName())
                        && field.getAnnotation(JsonFormat.class) == null
                        && item.get(field.getName()) != null) {
                    SimpleDateFormat aDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    item.put(field.getName(), aDate.format(new Date((Long) item.get(field.getName()))));
                }
            }
            items.add(item);
        }
    }


    private JSONObject getDataModel(Object data) {
        ObjectMapper mapper = new ObjectMapper();
        String json = "{}";
        try {
            json = mapper.writeValueAsString(data);
        } catch (JsonProcessingException e) {
            log.error("Json解析失败：" + e);
        }
        JSONObject item = JSONObject.parseObject(json);
        ObjConvertUtils o = new ObjConvertUtils();
        for (Field field : o.getAllFields(data)) {
            if (field.getAnnotation(Dict.class) != null) {
                String dictType = field.getAnnotation(Dict.class).dictCode();
                String text = field.getAnnotation(Dict.class).dictText();
                String table = field.getAnnotation(Dict.class).dictTable();
                String key = String.valueOf(item.get(field.getName()));
                if (!StringUtils.isBlank(table)) {
                    try {
                        if (ObjectUtils.isNotEmpty(key) & !"null".equals(key)) {
                            item.put(field.getName() + DICT_TEXT_SUFFIX, dictTypeService.dictTable(table, text, dictType, key));
                        } else {
                            item.put(field.getName() + DICT_TEXT_SUFFIX, null);
                        }
                    } catch (Exception e) {
                        throw new RuntimeException(field.getName() + "字段翻译异常");
                    }
                } else {
                    String textValue = translateDictValue(dictType, key);
                    // 走默认策略
                    item.put(field.getName() + DICT_TEXT_SUFFIX, textValue);
                }
            }
            if ("java.util.Date".equals(field.getType().getName())
                    && field.getAnnotation(JsonFormat.class) == null
                    && item.get(field.getName()) != null) {
                SimpleDateFormat aDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                item.put(field.getName(), aDate.format(new Date((Long) item.get(field.getName()))));
            }
        }
        return item;

    }

    /**
     * 翻译字典文本
     *
     * @param dictType
     * @param key
     * @return
     */
    private String translateDictValue(String dictType, String key) {
        if (StringUtils.isEmpty(key)) {
            return null;
        }
        String textValue = "";
        List<SysDictData> data = dictTypeService.selectDictDataByType(dictType);
        if (ObjectUtils.isEmpty(data)) {
            return textValue;
        }
        for (SysDictData sysDictData : data) {
            if (sysDictData.getDictValue().equals(key)) {
                textValue = sysDictData.getDictLabel();
            }
        }
        log.info("数据字典翻译: 字典类型：{}，当前翻译值：{}，翻译结果：{}", dictType, key, textValue);
        return textValue;
    }


    /**
     * 对象转换工具类
     */
    @SuppressWarnings("ALL")
    public class ObjConvertUtils {

        /**
         * 获取类的所有属性，包括父类
         *
         * @param object
         * @return
         */
        public Field[] getAllFields(Object object) {
            Class<?> clazz = object.getClass();
            List<Field> fieldList = new ArrayList<>();
            while (clazz != null) {
                fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
                clazz = clazz.getSuperclass();
            }
            Field[] fields = new Field[fieldList.size()];
            fieldList.toArray(fields);
            return fields;
        }

        public boolean isEmpty(Object object) {
            if (object == null) {
                return (true);
            }
            if ("".equals(object)) {
                return (true);
            }
            if ("null".equals(object)) {
                return (true);
            }
            return (false);
        }
    }

}
